package com.tang.consumer.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tang.consumer.domain.Request;
import com.tang.consumer.domain.Response;
import com.tang.consumer.netty.NettyClient;
import com.tang.consumer.utils.IdUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;

/**
 * @author Tang
 * @classname RpcProxy
 * @description [  ]
 * @date 2021/1/24 17:44
 */
@Component
public class RpcProxy<T> implements InvocationHandler {

    @Resource
    private NettyClient nettyClient;

    public RpcProxy() {

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }
        Request request = new Request();
        String requestId = IdUtil.getId();
        request.setId(requestId);
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParameterTypes(method.getParameterTypes());
        request.setParameters(args);
        Object result = nettyClient.send(request);
        Class<?> returnType = method.getReturnType();
        Response response = JSON.parseObject(JSON.toJSONString(result), Response.class);
        // 错误
        if (response.getCode() == 1) {
            throw new Exception(response.getErrorMsg());
        }
        if (returnType.isPrimitive() || String.class.isAssignableFrom(returnType)) {
            //返回值是 基本类型 || 字符串
            return response.getData();
        } else if (Collection.class.isAssignableFrom(returnType)) {
            // 返回值是集合
            return JSON.parseArray(JSON.toJSONString(result), Object.class);
        } else if (Map.class.isAssignableFrom(returnType)) {
            // 返回值是map
            return JSON.parseObject(JSON.toJSONString(result), Map.class);
        }else {
            // 转成要返回的类型
            Object data = response.getData();
            return JSONObject.parseObject(data.toString(), returnType);
        }
    }

}